// compress.ts - 数据压缩工具
// @/utils/monitor/utils/compress.ts

/**
 * 压缩字符串数据
 */
export async function compress(data: string): Promise<ArrayBuffer> {
  // #ifdef H5
  if (typeof window !== 'undefined') {
    // 检查是否支持压缩流 API (Chrome 103+)
    if ('CompressionStream' in window) {
      try {
        const encoder = new TextEncoder();
        const stream = new Response(encoder.encode(data)).body!
          .pipeThrough(new (window as any).CompressionStream('gzip'));
        
        return await new Response(stream).arrayBuffer();
      } catch (error) {
        console.warn('[Compress] CompressionStream failed, fallback to no compression:', error);
      }
    }
    
    // 降级方案：简单的字符串压缩（移除多余空格和换行）
    try {
      const compressed = simpleCompress(data);
      return new TextEncoder().encode(compressed).buffer;
    } catch (error) {
      console.warn('[Compress] Simple compression failed:', error);
    }
  }
  // #endif
  
  // 最终降级方案：不压缩
  return new TextEncoder().encode(data).buffer;
}

/**
 * 解压缩数据
 */
export async function decompress(data: ArrayBuffer): Promise<string> {
  // #ifdef H5
  if (typeof window !== 'undefined') {
    // 检查是否支持解压缩流 API
    if ('DecompressionStream' in window) {
      try {
        const stream = new Response(data).body!
          .pipeThrough(new (window as any).DecompressionStream('gzip'));
        
        const decompressed = await new Response(stream).arrayBuffer();
        return new TextDecoder().decode(decompressed);
      } catch (error) {
        console.warn('[Compress] DecompressionStream failed, fallback to direct decode:', error);
      }
    }
  }
  // #endif
  
  // 降级方案：直接解码
  return new TextDecoder().decode(data);
}

/**
 * 简单压缩（去除多余空格和换行）
 */
function simpleCompress(data: string): string {
  try {
    // 解析JSON并重新序列化（去除格式化）
    const parsed = JSON.parse(data);
    return JSON.stringify(parsed);
  } catch (error) {
    // 如果不是JSON，则简单去除多余空格
    return data
      .replace(/\s+/g, ' ')           // 多个空格替换为单个空格
      .replace(/\n\s*/g, '')          // 去除换行和缩进
      .replace(/\{\s+/g, '{')         // 去除对象开始的空格
      .replace(/\s+\}/g, '}')         // 去除对象结束的空格
      .replace(/\[\s+/g, '[')         // 去除数组开始的空格
      .replace(/\s+\]/g, ']')         // 去除数组结束的空格
      .replace(/,\s+/g, ',')          // 去除逗号后的空格
      .replace(/:\s+/g, ':')          // 去除冒号后的空格
      .trim();
  }
}

/**
 * 检查是否支持原生压缩
 */
export function isCompressionSupported(): boolean {
  // #ifdef H5
  if (typeof window !== 'undefined') {
    return 'CompressionStream' in window && 'DecompressionStream' in window;
  }
  // #endif
  
  return false;
}

/**
 * 获取数据大小（字节）
 */
export function getDataSize(data: string | ArrayBuffer): number {
  if (typeof data === 'string') {
    return new TextEncoder().encode(data).length;
  } else {
    return data.byteLength;
  }
}

/**
 * 计算压缩率
 */
export function calculateCompressionRatio(originalSize: number, compressedSize: number): number {
  if (originalSize === 0) return 0;
  return Math.round((1 - compressedSize / originalSize) * 100);
}

/**
 * 智能压缩（根据数据大小决定是否压缩）
 */
export async function smartCompress(data: string, threshold: number = 1024): Promise<{
  data: ArrayBuffer;
  compressed: boolean;
  originalSize: number;
  compressedSize: number;
  ratio: number;
}> {
  const originalSize = getDataSize(data);
  
  // 小于阈值的数据不压缩
  if (originalSize < threshold) {
    const buffer = new TextEncoder().encode(data).buffer;
    return {
      data: buffer,
      compressed: false,
      originalSize,
      compressedSize: originalSize,
      ratio: 0
    };
  }
  
  // 尝试压缩
  const compressedData = await compress(data);
  const compressedSize = compressedData.byteLength;
  const ratio = calculateCompressionRatio(originalSize, compressedSize);
  
  // 如果压缩后大小反而增加，则使用原始数据
  if (compressedSize >= originalSize) {
    const buffer = new TextEncoder().encode(data).buffer;
    return {
      data: buffer,
      compressed: false,
      originalSize,
      compressedSize: originalSize,
      ratio: 0
    };
  }
  
  return {
    data: compressedData,
    compressed: true,
    originalSize,
    compressedSize,
    ratio
  };
} 